// 导入验证模块Express-validator，在每个User上加数组，对body相关数据进行校验
const { body } = require('express-validator')
const validate = require('../middleware/validator')
const { User } = require('../model')
const md5 = require('../util/md5')

// 注册验证
exports.register = validate([
    // 1. 配置验证规则，使用withMessage定制错误消息。
    // .bail()为：如果验证失败，后面代码不继续执行，否则继续执行。
    // .custom为自定义验证方法
    body('user.username')
        .notEmpty().withMessage('用户名不能为空')
        .custom(
            // 验证用户名是否已经存在，为此我们需要操作数据库，导入model→index(可省略index，默认为index)
            async username => {
                const user = await User.findOne({ username })
                if (user) {
                    return Promise.reject('用户名已存在')
                }
            }
        ),

    body('user.password').notEmpty().withMessage('密码不能为空'),

    body('user.email')
        .notEmpty().withMessage('邮箱不能为空')
        .isEmail().withMessage('邮箱格式不正确')
        .bail()
        .custom(
            // 验证邮箱是否已经存在，为此我们需要操作数据库，导入model→index(可省略index，默认为index)
            async email => {
                const user = await User.findOne({ email })
                if (user) {
                    return Promise.reject('邮箱已存在')
                }
            }
        ),
])

// 登陆验证，按照代码顺序依次进行验证，只有前一个验证通过后，才会继续验证下一个
// 最外层用数组包裹
exports.login = [
    validate([
        body('user.email').notEmpty().withMessage('邮箱不能为空'),
        body('user.password').notEmpty().withMessage('密码不能为空')
    ]),
    validate([
        body('user.email').custom(async (email, { req }) => {
            // 通过使用.select()把model→user里的select为false的password给添加进来，否则后续密码无法返回过来
            // 把需要返回的信息都select上
            const user = await User.findOne({ email })
                .select(['email', 'username', 'bio', 'image', 'password'])
            if (!user) {
                return Promise.reject('用户不存在')
            }
            // 如果查到了，将数据挂载到请求对象中，后续的中间件也可以进行使用
            req.user = user
        })
    ]),
    validate([
        body('user.password').custom(async (password, {req}) => {
            console.log(req.user);
            // 此处直接调用md5，所以也会自动加上私钥，不会暴露私钥手动添加，更安全
            if (md5(password) !== req.user.password) {
                return Promise.reject('密码错误')
            }
        })
    ]),
]
